namespace DotNetNuke.Services.Url.FriendlyUrl
{
    using DotNetNuke.Common;
    using DotNetNuke.Common.Utilities;
    using DotNetNuke.Entities.Portals;
    using DotNetNuke.Entities.Tabs;
    using DotNetNuke.Framework.Providers;
    using Microsoft.VisualBasic.CompilerServices;
    using System;
    using System.Text.RegularExpressions;
    using System.Web;

    public class DNNFriendlyUrlProvider : FriendlyUrlProvider
    {
        private bool _includePageName;
        private ProviderConfiguration _providerConfiguration = ProviderConfiguration.GetProviderConfiguration("friendlyUrl");
        private string _regexMatch;
        private const string ProviderType = "friendlyUrl";
        private const string RegexMatchExpression = "[^a-zA-Z0-9 ]";

        public DNNFriendlyUrlProvider()
        {
            Provider objProvider = (Provider) this._providerConfiguration.Providers[this._providerConfiguration.DefaultProvider];
            if (Convert.ToString(objProvider.Attributes["includePageName"]) != "")
            {
                this._includePageName = bool.Parse(objProvider.Attributes["includePageName"]);
            }
            else
            {
                this._includePageName = true;
            }
            if (Convert.ToString(objProvider.Attributes["includePageName"]) != "")
            {
                this._includePageName = bool.Parse(objProvider.Attributes["includePageName"]);
            }
            else
            {
                this._includePageName = true;
            }
            if (Convert.ToString(objProvider.Attributes["regexMatch"]) != "")
            {
                this._regexMatch = objProvider.Attributes["regexMatch"];
            }
            else
            {
                this._regexMatch = "[^a-zA-Z0-9 ]";
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// AddPage adds the page to the friendly url
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="path">The path to format.</param>
        /// <param name="pageName">The page name.</param>
        /// <returns>The formatted url</returns>
        /// <history>
        /// [cnurse]	12/16/2004	created
        /// </history>
        /// -----------------------------------------------------------------------------
        private string AddPage(string path, string pageName)
        {
            string friendlyPath = path;
            if (friendlyPath.EndsWith("/"))
            {
                return (friendlyPath + pageName);
            }
            return (friendlyPath + "/" + pageName);
        }

        public override string FriendlyUrl(TabInfo tab, string path)
        {
            PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
            return this.FriendlyUrl(tab, path, "Default.aspx", _portalSettings);
        }

        public override string FriendlyUrl(TabInfo tab, string path, string pageName)
        {
            PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
            return this.FriendlyUrl(tab, path, pageName, _portalSettings);
        }

        public override string FriendlyUrl(TabInfo tab, string path, string pageName, PortalSettings settings)
        {
            string friendlyPath = path;
            friendlyPath = this.GetFriendlyAlias(path, settings.PortalAlias.HTTPAlias);
            return this.GetFriendlyQueryString(tab, friendlyPath, settings, pageName);
        }

        public override string FriendlyUrl(TabInfo tab, string path, string pageName, string portalAlias)
        {
            string friendlyPath = path;
            friendlyPath = this.GetFriendlyAlias(path, portalAlias);
            return this.GetFriendlyQueryString(tab, friendlyPath, pageName);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// GetFriendlyAlias gets the Alias root of the friendly url
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="path">The path to format.</param>
        /// <param name="portalAlias">The portal alias of the site.</param>
        /// <returns>The formatted url</returns>
        /// <history>
        /// [cnurse]	12/16/2004	created
        /// </history>
        /// -----------------------------------------------------------------------------
        private string GetFriendlyAlias(string path, string portalAlias)
        {
            string friendlyPath = path;
            string matchString = "";
            if ((portalAlias != Null.NullString) && (HttpContext.Current.Items["UrlRewrite:OriginalUrl"] != null))
            {
                string originalUrl = HttpContext.Current.Items["UrlRewrite:OriginalUrl"].ToString();
                if (Regex.Match(originalUrl, "^" + Globals.AddHTTP(portalAlias), RegexOptions.IgnoreCase) != Match.Empty)
                {
                    matchString = Globals.AddHTTP(portalAlias);
                }
                if ((matchString == "") && (Regex.Match(originalUrl, "^?alias=" + portalAlias, RegexOptions.IgnoreCase) != Match.Empty))
                {
                    matchString = Globals.AddHTTP(portalAlias);
                }
            }
            if (matchString == "")
            {
                return Globals.ResolveUrl(friendlyPath);
            }
            if (path.IndexOf("~") != -1)
            {
                return friendlyPath.Replace("~", matchString);
            }
            return (matchString + friendlyPath);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// GetFriendlyQueryString gets the Querystring part of the friendly url
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="tab">The tab whose url is being formatted.</param>
        /// <param name="path">The path to format.</param>
        /// <returns>The formatted url</returns>
        /// <history>
        /// [cnurse]	12/16/2004	created
        /// [smcculloch]10/10/2005	Regex update for rewritten characters
        /// </history>
        /// -----------------------------------------------------------------------------
        private string GetFriendlyQueryString(TabInfo tab, string path, string pageName)
        {
            string friendlyPath = path;
            Match queryStringMatch = Regex.Match(friendlyPath, @"(.[^\\?]*)\\?(.*)", RegexOptions.IgnoreCase);
            string queryStringSpecialChars = "";
            if (queryStringMatch != Match.Empty)
            {
                friendlyPath = Regex.Replace(queryStringMatch.Groups[1].Value, "Default.aspx", "", RegexOptions.IgnoreCase);
                string queryString = queryStringMatch.Groups[2].Value.Replace("&amp;", "&");
                if (queryString.StartsWith("?"))
                {
                    queryString = queryString.TrimStart(new char[] { Convert.ToChar("?") });
                }
                string[] nameValuePairs = queryString.Split(new char[] { Convert.ToChar("&") });
                int refIntHelperL0 = nameValuePairs.Length - 1;
                for (int i = 0; i <= refIntHelperL0; i++)
                {
                    string pathToAppend = "";
                    string[] pair = nameValuePairs[i].Split(new char[] { Convert.ToChar("=") });
                    if (friendlyPath.EndsWith("/"))
                    {
                        pathToAppend = pathToAppend + pair[0];
                    }
                    else
                    {
                        pathToAppend = pathToAppend + "/" + pair[0];
                    }
                    if (pair.Length > 1)
                    {
                        char refCharHelperS0;
                        if (pair[1].Length > 0)
                        {
                            if (!Regex.IsMatch(pair[1], this._regexMatch))
                            {
                                if (((pair[0].ToLower() == "tabid") && Versioned.IsNumeric(pair[1])) && (tab != null))
                                {
                                    int tabId = Convert.ToInt32(pair[1]);
                                    if ((tab.TabID == tabId) && ((tab.TabPath != Null.NullString) & this.IncludePageName))
                                    {
                                        pathToAppend = tab.TabPath.Replace("//", "/").TrimStart(new char[] { '/' }) + "/" + pathToAppend;
                                    }
                                }
                                refCharHelperS0 = ' ';
                                pathToAppend = pathToAppend + "/" + pair[1].Replace(" ", HttpUtility.UrlEncode(refCharHelperS0.ToString()));
                            }
                            else
                            {
                                if (queryStringSpecialChars.Length == 0)
                                {
                                    queryStringSpecialChars = pair[0] + "=" + pair[1];
                                }
                                else
                                {
                                    queryStringSpecialChars = queryStringSpecialChars + "&" + pair[0] + "=" + pair[1];
                                }
                                pathToAppend = "";
                            }
                        }
                        else
                        {
                            refCharHelperS0 = ' ';
                            pathToAppend = pathToAppend + "/" + HttpUtility.UrlEncode(refCharHelperS0.ToString());
                        }
                    }
                    friendlyPath = friendlyPath + pathToAppend;
                }
            }
            if (queryStringSpecialChars.Length > 0)
            {
                return (this.AddPage(friendlyPath, pageName) + "?" + queryStringSpecialChars);
            }
            return this.AddPage(friendlyPath, pageName);
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// GetFriendlyQueryString gets the Querystring part of the friendly url
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="path">The path to format.</param>
        /// <param name="settings">The Portal Settings for the site.</param>
        /// <returns>The formatted url</returns>
        /// <history>
        /// [cnurse]	12/16/2004	created
        /// [smcculloch]10/10/2005	Regex update for rewritten characters
        /// </history>
        /// -----------------------------------------------------------------------------
        private string GetFriendlyQueryString(TabInfo tab, string path, PortalSettings settings, string pageName)
        {
            string friendlyPath = path;
            Match queryStringMatch = Regex.Match(friendlyPath, @"(.[^\\?]*)\\?(.*)", RegexOptions.IgnoreCase);
            string queryStringSpecialChars = "";
            if (queryStringMatch != Match.Empty)
            {
                friendlyPath = Regex.Replace(queryStringMatch.Groups[1].Value, "Default.aspx", "", RegexOptions.IgnoreCase);
                string queryString = queryStringMatch.Groups[2].Value.Replace("&amp;", "&");
                if (queryString.StartsWith("?"))
                {
                    queryString = queryString.TrimStart(new char[] { Convert.ToChar("?") });
                }
                string[] nameValuePairs = queryString.Split(new char[] { Convert.ToChar("&") });
                int refIntHelperL0 = nameValuePairs.Length - 1;
                for (int i = 0; i <= refIntHelperL0; i++)
                {
                    string pathToAppend = "";
                    string[] pair = nameValuePairs[i].Split(new char[] { Convert.ToChar("=") });
                    if (friendlyPath.EndsWith("/"))
                    {
                        pathToAppend = pathToAppend + pair[0];
                    }
                    else
                    {
                        pathToAppend = pathToAppend + "/" + pair[0];
                    }
                    if (pair.Length > 1)
                    {
                        char refCharHelperS0;
                        if (pair[1].Length > 0)
                        {
                            if (!Regex.IsMatch(pair[1], this._regexMatch))
                            {
                                if (((pair[0].ToLower() == "tabid") && Versioned.IsNumeric(pair[1])) && (tab != null))
                                {
                                    int tabId = Convert.ToInt32(pair[1]);
                                    if ((tab.TabID == tabId) && ((tab.TabPath != Null.NullString) & this.IncludePageName))
                                    {
                                        pathToAppend = tab.TabPath.Replace("//", "/").TrimStart(new char[] { '/' }) + "/" + pathToAppend;
                                    }
                                }
                                refCharHelperS0 = ' ';
                                pathToAppend = pathToAppend + "/" + pair[1].Replace(" ", HttpUtility.UrlEncode(refCharHelperS0.ToString()));
                            }
                            else
                            {
                                if (queryStringSpecialChars.Length == 0)
                                {
                                    queryStringSpecialChars = pair[0] + "=" + pair[1];
                                }
                                else
                                {
                                    queryStringSpecialChars = queryStringSpecialChars + "&" + pair[0] + "=" + pair[1];
                                }
                                pathToAppend = "";
                            }
                        }
                        else
                        {
                            refCharHelperS0 = ' ';
                            pathToAppend = pathToAppend + "/" + HttpUtility.UrlEncode(refCharHelperS0.ToString());
                        }
                    }
                    friendlyPath = friendlyPath + pathToAppend;
                }
            }
            if (queryStringSpecialChars.Length > 0)
            {
                return (this.AddPage(friendlyPath, pageName) + "?" + queryStringSpecialChars);
            }
            return this.AddPage(friendlyPath, pageName);
        }

        public bool IncludePageName
        {
            get
            {
                return this._includePageName;
            }
        }

        public string RegexMatch
        {
            get
            {
                return this._regexMatch;
            }
        }
    }
}

